/**
 * Copyright (c) qzsoft All rights reserved.
 * <p>
 * qzsoft.cn
 * <p>
 * 版权所有，侵权必究！
 */

package com.qzsoft.system.modules.permission.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qzsoft.jeemis.common.cacheutils.CacheGenUtils;
import com.qzsoft.jeemis.common.constant.Constant;
import com.qzsoft.jeemis.common.enums.SuperAdminEnum;
import com.qzsoft.jeemis.common.exception.ErrorCode;
import com.qzsoft.jeemis.common.exception.RenException;
import com.qzsoft.jeemis.common.query.ConditionBuilder;
import com.qzsoft.jeemis.common.query.ConditionDTO;
import com.qzsoft.jeemis.common.service.BaseService;
import com.qzsoft.jeemis.common.utils.Collections3;
import com.qzsoft.jeemis.common.utils.ConvertUtils;
import com.qzsoft.jeemis.platform.dict.service.BasicCodeEditService;
import com.qzsoft.jeemis.platform.security.password.PasswordUtils;
import com.qzsoft.jeemis.platform.security.user.SecurityUser;
import com.qzsoft.jeemis.platform.security.user.UserDetail;
import com.qzsoft.jeemis.platform.user.dto.DeptAndUserDTO;
import com.qzsoft.jeemis.repository.sqlmapper.SqlMapper;
import com.qzsoft.jeemis.repository.sys.entity.BasicDeptEntity;
import com.qzsoft.jeemis.repository.sys.entity.BasicUserEntity;
import com.qzsoft.system.common.CommonUtils;
import com.qzsoft.system.modules.permission.dept.service.SysDeptService;
import com.qzsoft.system.modules.permission.deptJob.service.SysUserDeptService;
import com.qzsoft.system.modules.permission.role.service.SysRoleUserService;
import com.qzsoft.system.modules.permission.rolebusiness.dto.SysUserRoleBusinessVo;
import com.qzsoft.system.modules.permission.rolebusiness.service.SysUserRoleBusinessService;
import com.qzsoft.system.modules.permission.user.common.Dict;
import com.qzsoft.system.modules.permission.user.common.Query;
import com.qzsoft.system.modules.permission.user.dto.PasswordDTO;
import com.qzsoft.system.modules.permission.user.dto.SysUserDTO;
import com.qzsoft.system.modules.permission.user.dto.SysUserInfoDto;
import com.qzsoft.system.modules.permission.user.dto.UserTypeDTO;
import com.qzsoft.system.modules.permission.user.service.SysUserService;
import com.qzsoft.system.modules.zhjdlogin.dao.PasswordValidDao;
import com.qzsoft.system.repository.sys.dao.SysUserDao;
import com.qzsoft.system.repository.sys.entity.SysUserEntity;
import com.qzsoft.zhjd.common.enums.BizCode;
import com.qzsoft.zhjd.common.utils.RenExceptionUtils;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;

/**
 * 系统用户
 *
 * @author
 */
@Service
public class SysUserServiceImpl extends BaseService implements SysUserService {
    @Autowired
    private SysRoleUserService sysRoleUserService;
    @Autowired
    private SysDeptService sysDeptService;
    @Autowired
    private SysUserDao sysUserDao;

    /*************** 2020-10-10 15:25:50 代码迁移 高丙祥 ADD START ***************/
    @Autowired
    BasicCodeEditService basicCodeEditService;
    @Autowired
    SysUserDeptService sysUserDeptService;
    @Autowired
    private SqlSession sqlSession;
    @Autowired
    private SysUserRoleBusinessService sysUserRoleBusinessService;
    /*************** 2020-10-10 15:50:50 代码迁移 高丙祥 ADD END ***************/

    @Autowired
    private PasswordValidDao passwordValidDao;

    @Override
    public IPage<SysUserEntity> page(Map<String, Object> params) {
        UserDetail userDetail = this.basegetLoginUser();
        // 分页
        IPage<SysUserEntity> page = getPage(params, Constant.CREATE_DATE, false, SysUserEntity.class);

        QueryWrapper<SysUserEntity> query = this.getQueryWrapper(params, SysUserEntity.class, "username");
        if (!ObjectUtils.isEmpty(params.get("deptId"))) {
            query.likeRight("dept_id", params.get("deptId"));
        }
        // 普通管理员，只能查询所属部门及子部门的数据
        if (userDetail.getSuperAdmin() == SuperAdminEnum.NO.value()) {
            query.likeRight("dept_id", userDetail.getDeptId());
        }
        // 查询
        IPage<SysUserEntity> list = sysUserDao.selectPage(page, query);
        return list;
    }

    @Override
    public List<SysUserEntity> list(Map<String, Object> params) {
        // 通用条件生成器
        QueryWrapper<SysUserEntity> queryUser = this.getQueryWrapper(params, SysUserEntity.class, "username");

        List<SysUserEntity> sysUserList = sysUserDao.selectList(queryUser);
        return sysUserList;
    }

    private QueryWrapper<SysUserEntity> getQueryWrapperx(Map<String, Object> params) {
        UserDetail userDetail = this.basegetLoginUser();
        QueryWrapper<SysUserEntity> queryUser = new QueryWrapper<>();
        // 普通管理员，只能查询所属部门及子部门的数据
        queryUser.allEq(params);
        if (userDetail.getSuperAdmin() == SuperAdminEnum.NO.value()) {
            queryUser.likeRight("dept_id", userDetail.getDeptId());
        }
        return queryUser;
    }

    private QueryWrapper<SysUserEntity> getQueryWrapperx(ConditionDTO condition) {
        ConditionBuilder conditionBuilder = new ConditionBuilder();
        conditionBuilder.addCondition(condition);
        UserDetail userDetail = this.basegetLoginUser();
        QueryWrapper<SysUserEntity> queryUser = conditionBuilder.toQueryWrapper();
        // 普通管理员，只能查询所属部门及子部门的数据
        if (userDetail.getSuperAdmin() == SuperAdminEnum.NO.value()) {
            queryUser.likeRight("dept_id", userDetail.getDeptId());
        }
        return queryUser;
    }

    @Override
    public SysUserDTO get(Long id) {
        SysUserEntity entity = sysUserDao.selectById(id);
        // 查询当前用户的审批角色
        List<SysUserRoleBusinessVo> sysUserRoleBusinessVos = sysUserRoleBusinessService
                .queryUserRoleBusinessListByUserId(id);
        SysUserDTO sysUserDTO = ConvertUtils.sourceToTarget(entity, SysUserDTO.class);
        sysUserDTO.setRoleBusinessList(sysUserRoleBusinessVos);
        return sysUserDTO;
    }

    @Override
    public SysUserDTO getByUsername(String username) {
        QueryWrapper<SysUserEntity> queryUser = new QueryWrapper<>();
        queryUser.eq("username", username);
        SysUserEntity entity = sysUserDao.selectOne(queryUser);
        return ConvertUtils.sourceToTarget(entity, SysUserDTO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SysUserDTO dto) {
        // 用户名不可重复
        QueryWrapper<SysUserEntity> queryUser = new QueryWrapper<>();
        queryUser.eq("username", dto.getUsername());
        Integer count = sysUserDao.selectCount(queryUser);
        if (null != count && 0 < count.intValue()) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "用户名[" + dto.getUsername() + "]已经存在");
        }

        SysUserEntity entity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class);

        // 校验密码
        String password = entity.getPassword();
        Map<String, Object> returnMap = passwordValidDao.createReturnMap();
        passwordValidDao.validatePassword(password, returnMap);
        String code = null == returnMap.get("code") ? "" : returnMap.get("code").toString();
        String msg = null == returnMap.get("msg") ? "" : returnMap.get("msg").toString();
        if (!"200".equals(code)) {
            throw new RenException(msg);
        }
        
        // 密码加密
        password = PasswordUtils.encode(password);
        entity.setPassword(password);

        // 保存用户
        // 处理用户的deppkid
        entity.setSuperAdmin(SuperAdminEnum.NO.value());
        entity.setDeptPkid(sysDeptService.getDeptPkIdById(entity.getDeptId()));
        String deptName = sysDeptService.get(sysDeptService.getDeptPkIdById(entity.getDeptId())).getName();
        entity.setDeptName(deptName);
        entity.setHasDelete(0);
        sysUserDao.insert(entity);

        // 保存角色用户关系
        sysRoleUserService.saveOrUpdate(entity.getId(), dto.getRoleIdList());

        // 保存用户业务角色关系
        sysUserRoleBusinessService.saveOrUpdate(entity.getId(), dto.getRoleBusinessList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysUserDTO dto) {
        SysUserEntity entity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class);

        // 密码加密
        if (StringUtils.isBlank(dto.getPassword())) {
            entity.setPassword(null);
        } else {
            // 校验密码
            String newPassword = entity.getPassword();
            Map<String, Object> map = passwordValidDao.validateResetPassword(entity.getId(), newPassword);
            String code = null == map.get("code") ? "" : map.get("code").toString();
            String msg = null == map.get("msg") ? "" : map.get("msg").toString();
            if (!"200".equals(code)) {
                throw new RenException(msg);
            }
            
            // 密码加密
            String password = PasswordUtils.encode(newPassword);
            entity.setPassword(password);
        }

        // 更新用户
        entity.setDeptPkid(sysDeptService.getDeptPkIdById(entity.getDeptId()));

        /*************** 2020-10-12 20:18:50 代码迁移 高丙祥 ADD START ***************/
        String deptName = sysDeptService.get(sysDeptService.getDeptPkIdById(entity.getDeptId())).getName();
        entity.setDeptName(deptName);
        /*************** 2020-10-12 20:18:50 代码迁移 高丙祥 ADD START ***************/

        entity.setHasDelete(0);
        sysUserDao.updateById(entity);

        // 更新角色用户关系
        sysRoleUserService.saveOrUpdate(entity.getId(), dto.getRoleIdList());

        // 更新用户业务角色关系
        sysUserRoleBusinessService.saveOrUpdate(entity.getId(), dto.getRoleBusinessList());
    }

    @Override
    public void delete(Long[] ids) {
        // 删除用户
        sysUserDao.deleteBatchIds(Arrays.asList(ids));

        // 删除角色用户关系
        sysRoleUserService.deleteByUserIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(PasswordDTO passwordDTO) {
        UserDetail user = SecurityUser.getUser();
        SysUserEntity userEntity = sysUserDao.selectById(user.getId());
        // 原密码不正确
        if (!PasswordUtils.matches(passwordDTO.getPassword(), userEntity.getPassword())) {
            throw (new RenException(ErrorCode.PASSWORD_ERROR));
        }

        // 校验新密码
        String newPassword = passwordDTO.getNewPassword();
        Map<String, Object> map = passwordValidDao.validateResetPassword(user.getId(), newPassword);
        String code = null == map.get("code") ? "" : map.get("code").toString();
        String msg = null == map.get("msg") ? "" : map.get("msg").toString();
        if (!"200".equals(code)) {
            throw new RenException(msg);
        }

        // 执行更新
        newPassword = PasswordUtils.encode(newPassword);
        UpdateWrapper<SysUserEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", userEntity.getId()).set("password", newPassword);
        sysUserDao.update(new SysUserEntity(), updateWrapper);
        CacheGenUtils.delete(CacheGenUtils.SYS_USER_DETAIL + userEntity.getId());
    }

    @Override
    public void deleteBatchIds(Collection<? extends Serializable> idList) {
        sysUserDao.deleteBatchIds(idList);
    }

    @Override
    public int getCountByDeptId(String deptPkId) {
        QueryWrapper<SysUserEntity> queryUser = new QueryWrapper<>();
        queryUser.eq("dept_pkid", deptPkId);
        return sysUserDao.selectCount(queryUser);
    }

    @Override
    public List<SysUserEntity> getUserByDeptId(String deptId) {
        QueryWrapper<SysUserEntity> queryUser = new QueryWrapper<>();
        queryUser.eq("dept_id", deptId);
        return sysUserDao.selectList(queryUser);
    }

    @Override
    public List<Map> getUserByUserName(String userName) {
        return sysUserDao.getUserByUserName(userName);

    }

    @Override
    public List<SysUserDTO> queryUserWithType(List<String> utList) {
//        List<SysUserDTO> arrayListQltdUser = new ArrayList<>();
//        for (UserTypeDTO userTypeDTO : utList) {
//            String approvalType = userTypeDTO.getApprovalType();
//            String approvalValue = userTypeDTO.getApprovalValue();
//            QueryWrapper<SysUserEntity> queryUser = new QueryWrapper<>();
//            if ("choose_user".equals(approvalType)) {
//                queryUser.eq("id", approvalValue);
//            } else if ("choose_dept".equals(approvalType)) {
//                queryUser.eq("dept_id", approvalValue);
//            } else if ("choose_post".equals(approvalType)) {
//                //queryUser.eq("dept_id",approvalValue);
//            }
//            List<SysUserEntity> sysUserEntities = sysUserDao.selectList(queryUser);
//            List<SysUserDTO> sysUserDTOList = ConvertUtils.sourceToTarget(sysUserEntities, SysUserDTO.class);
//            arrayListQltdUser.addAll(sysUserDTOList);
//        }
        QueryWrapper<SysUserEntity> sysUserEntityQueryWrapper = new QueryWrapper<>();
        sysUserEntityQueryWrapper.in("username", utList);
        List<SysUserEntity> sysUserEntities = sysUserDao.selectList(sysUserEntityQueryWrapper);
        return ConvertUtils.sourceToTarget(sysUserEntities, SysUserDTO.class);
//        return arrayListQltdUser;

    }

    @Override
    public List<SysUserEntity> queryByUserIds(List utList) {
        QueryWrapper<SysUserEntity> sysUserEntityQueryWrapper = new QueryWrapper<>();
        sysUserEntityQueryWrapper.in("username", utList);
//        return sysUserDao.selectBatchIds(utList);
        return sysUserDao.selectList(sysUserEntityQueryWrapper);
    }

    /*************** 2020-10-10 15:25:50 代码迁移 高丙祥 ADD START ***************/
    /**
     * @param params
     * @return
     * @author gbx
     */
    @Override
    public IPage<SysUserInfoDto> getListPage(Map<String, Object> params) {
        Page<SysUserInfoDto> page = new Query<SysUserInfoDto>(params).getPage();
//        boolean flag = false;
        if (CommonUtils.checkStringObject(params.get(Dict.DEPT_NAME))) {
            String deptName = (String) params.get(Dict.DEPT_NAME);
            if (CommonUtils.check(deptName)) {
//                flag = true;
                deptName = CommonUtils.replaceSqlLikeField(deptName);
                System.out.println("deptName:" + deptName);
                params.put(Dict.DEPT_NAME, deptName);
            }
        }
        if (CommonUtils.checkStringObject(params.get(Dict.REAL_NAME))) {
            String realName = (String) params.get(Dict.REAL_NAME);
            if (CommonUtils.check(realName)) {
//                flag = true;
                realName = CommonUtils.replaceSqlLikeField((String) params.get(Dict.REAL_NAME));
                System.out.println("realName:" + realName);
                params.put(Dict.REAL_NAME, realName);
            }
        }
        if (CommonUtils.checkStringObject(params.get(Dict.JOB_NAME))) {
            String jobName = (String) params.get(Dict.JOB_NAME);
            if (CommonUtils.check(jobName)) {
//                flag = true;
                jobName = CommonUtils.replaceSqlLikeField((String) params.get(Dict.JOB_NAME));
                System.out.println("jobName:" + jobName);
                params.put(Dict.JOB_NAME, jobName);
            }
        }
//        params.put("flag",flag);
        boolean validateRoleId = params.get("roleId") != null && !"".equals((String) params.get("roleId"));
        boolean validateId = params.get("deptId") != null && !"".equals((String) params.get("deptId"));
        boolean validateCode = params.get("deptCode") != null && !"".equals((String) params.get("deptCode"));
        boolean hasChildren = true;
        List<SysUserInfoDto> list = new ArrayList<>();
        if (params.get("hasChildren") != null) {
            hasChildren = Boolean.valueOf((String) params.get("hasChildren"));
        }
        if (validateId) {
            list = sysUserDao.getListPageInDeptAndChildren(page, params);
        }
        if (validateCode && hasChildren) {
            list = sysUserDao.getListPageInDeptAndChildren(page, params);
        }
        if (validateCode && !hasChildren) {
            list = sysUserDao.getListPageInDept(page, params);
        }
        if (!validateId && !validateCode && hasChildren) {
            list = sysUserDao.getListPage(page, params);
        }
        if (!validateId && !validateCode && !hasChildren) {
            list = sysUserDao.getListPageInSysUser(page, params);
        }
//        list = sysUserDao.getListPage(page, params);
        page.setRecords(list);
        return page;
    }

    /**
     * 获取当前用户信息
     *
     * @param id 用户表主键
     * @return 查询结果
     */
    @Override
    public SysUserDTO getCurrentUserInfo(Long id) {
        SysUserEntity entity = sysUserDao.selectById(id);
        SysUserDTO sysUserDTO = ConvertUtils.sourceToTarget(entity, SysUserDTO.class);
        return sysUserDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCurrentUserInfo(SysUserDTO sysUserDTO) {
        SysUserEntity entity = ConvertUtils.sourceToTarget(sysUserDTO, SysUserEntity.class);
        sysUserDao.updateById(entity);
    }

    /*************** 2020-10-10 15:50:50 代码迁移 高丙祥 ADD END ***************/

// l李化军修改
    public List<DeptAndUserDTO> getDeptAndUsers(String pid) {
        List<DeptAndUserDTO> deptAndUserDTOList = new ArrayList();
        SqlMapper sqlMapper = new SqlMapper(this.sqlSession);
        String strSql = "select id,pkid,name from sys_dept where pid=#{0} ";
        List<BasicDeptEntity> deptList = sqlMapper.selectListArgs(strSql, BasicDeptEntity.class, new Object[] { pid });
        strSql = "select count(*) as countV,dept_id as deptId from sys_user where dept_id in (select id from sys_dept where pid=#{0}) and has_delete = 0 group by dept_id";
        List<Map<String, Object>> countList = sqlMapper.selectListArgs(strSql, new Object[] { pid });
        Map<String, Object> mapCount = Collections3.listToMap3(countList, "deptId", "countV");

        DeptAndUserDTO deptDTO;
        for (Iterator var8 = deptList.iterator(); var8.hasNext(); deptAndUserDTOList.add(deptDTO)) {
            BasicDeptEntity deptEntity = (BasicDeptEntity) var8.next();
            deptDTO = new DeptAndUserDTO();
            deptDTO.setId(deptEntity.getId());
            deptDTO.setDeptPkid(deptEntity.getPkid());
            deptDTO.setDeptId(deptEntity.getId());
            deptDTO.setName(deptEntity.getName());
            deptDTO.setHasDept(true);
            deptDTO.setChecked(false);
            deptDTO.setCount(0L);
            if (mapCount.containsKey(deptDTO.getId())) {
                String strKey = String.valueOf(deptDTO.getId());
                deptDTO.setCount(Long.parseLong(String.valueOf(mapCount.get(strKey))));
            }
        }

        strSql = "select id,username ,real_name,dept_id,head_url from sys_user where dept_id=#{0} and status=1  and has_delete = 0";
        List<BasicUserEntity> userList = sqlMapper.selectListArgs(strSql, BasicUserEntity.class, new Object[] { pid });
        Iterator var13 = userList.iterator();

        while (var13.hasNext()) {
            BasicUserEntity userEntity = (BasicUserEntity) var13.next();
            DeptAndUserDTO userDTO = new DeptAndUserDTO();
            userDTO.setId(userEntity.getUsername());
            userDTO.setName(userEntity.getRealName());
            userDTO.setRealName(userEntity.getRealName());
            userDTO.setDeptPkid(userEntity.getDeptPkid());
            userDTO.setDeptId(userEntity.getDeptId());
            userDTO.setHasDept(false);
            userDTO.setChecked(false);
            userDTO.setCount(0L);
            deptAndUserDTOList.add(userDTO);
        }

        return deptAndUserDTOList;
    }

    public List<DeptAndUserDTO> getSelectDeptAndUser(String pid) {
        return null;
    }

    public List<DeptAndUserDTO> getSearchDeptAndUser(String key) {
        List<DeptAndUserDTO> deptAndUserDTOList = new ArrayList();
        SqlMapper sqlMapper = new SqlMapper(this.sqlSession);
        String strSql = "select id,pkid,name from sys_dept where spell like #{0} or name like #{1}";
        IPage paga = new Page(0L, 30L);
        List<BasicDeptEntity> deptList = sqlMapper.selectListArgs(paga, strSql, BasicDeptEntity.class,
                new Object[] { key + "%", "%" + key + "%" });
        strSql = "select count(*) as countV from sys_user where dept_id = #{0}";
        Iterator var7 = deptList.iterator();

        DeptAndUserDTO userDTO;
        while (var7.hasNext()) {
            BasicDeptEntity deptEntity = (BasicDeptEntity) var7.next();
            Long count = sqlMapper.selectValueLongArgs(strSql, 0L, new Object[] { deptEntity.getId() });
            userDTO = new DeptAndUserDTO();
            userDTO.setId(deptEntity.getId());
            userDTO.setDeptPkid(deptEntity.getPkid());
            userDTO.setDeptId(deptEntity.getId());
            userDTO.setName(deptEntity.getName());
            userDTO.setHasDept(true);
            userDTO.setChecked(false);
            userDTO.setCount(count);
            deptAndUserDTOList.add(userDTO);
        }

        strSql = "select id,username ,real_name,dept_id,dept_pkid,head_url from sys_user where (spell like #{0} or real_name like #{0} or username like #{0}) and status=1  and has_delete = 0";
        paga = new Page(0L, 300L);
        List<BasicUserEntity> userList = sqlMapper.selectListArgs(paga, strSql, BasicUserEntity.class,
                new Object[] { key + "%", "%" + key + "%" });
        Iterator var12 = userList.iterator();

        while (var12.hasNext()) {
            BasicUserEntity userEntity = (BasicUserEntity) var12.next();
            userDTO = new DeptAndUserDTO();
            userDTO.setId(userEntity.getUsername());
            userDTO.setName(userEntity.getRealName());
            userDTO.setDeptPkid(userEntity.getDeptPkid());
            userDTO.setDeptId(userEntity.getDeptId());
            userDTO.setHasDept(false);
            userDTO.setChecked(false);
            userDTO.setCount(0L);
            deptAndUserDTOList.add(userDTO);
        }

        return deptAndUserDTOList;
    }
    // 李化军修改结束

    @Override
    public IPage<SysUserInfoDto> poundsPage(Map<String, Object> map) {
        Page<SysUserInfoDto> page = new Page<>(Integer.parseInt(String.valueOf(map.get("current"))),
                Integer.parseInt(String.valueOf(map.get("size"))));
        IPage<SysUserInfoDto> pageList = sysUserDao.getWaagPageList(page, map);
        return pageList;
    }
}
